//
//  ImageRender.m
//  Runner
//
//  Created by BqLin on 2020/10/16.
//

#import "ImageRender.h"
#import <UIKit/UIKit.h>
#import <CoreVideo/CoreVideo.h>

@interface ImageRender ()

@property (nonatomic, strong) UIImage *image;
@property (nonatomic, assign) size_t width;
@property (nonatomic, assign) size_t height;
@property (nonatomic, assign) CVPixelBufferRef pixelBufferRef;

@end


@implementation ImageRender

- (instancetype)initWithImageName:(NSString *)imageName {
    self = [super init];
    
    _image = [UIImage imageNamed:imageName];
    [self createCVBuffer:&_pixelBufferRef];
    return self;
}

- (void)createCVBuffer:(CVPixelBufferRef *)target {
    CGImageRef imageRef = _image.CGImage;
    _width = CGImageGetWidth(imageRef);
    _height = CGImageGetHeight(imageRef);
    
    CFDictionaryRef empty;
    CFMutableDictionaryRef attrs;
    empty = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    
    CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty);
    CVPixelBufferCreate(kCFAllocatorDefault, _width, _height, kCVPixelFormatType_32BGRA, attrs, target);
    
    CFRelease(empty);
    CFRelease(attrs);
}

- (void)renderImage {
    CVPixelBufferLockBaseAddress(_pixelBufferRef, 0);
    
    void *dataRef = CVPixelBufferGetBaseAddress(_pixelBufferRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(dataRef, _width, _height, 8, CVPixelBufferGetBytesPerRow(_pixelBufferRef), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGContextDrawImage(context, CGRectMake(0, 0, _width, _height), _image.CGImage);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    
    CVPixelBufferUnlockBaseAddress(_pixelBufferRef, 0);
}

- (void)renderWithCompletion:(void (^)(void))completion {
    [self renderImage];
    if (completion) completion();
}

- (CVPixelBufferRef)copyPixelBuffer {
    CVBufferRetain(_pixelBufferRef);
    return _pixelBufferRef;
}

@end
